<script lang="ts">
	export let data: { chatMsg?: Message[] } = {}; // 添加类型注解
	import { knowledge1, storageFiles } from "$lib/shared/stores/common/Store";
	import { onMount } from "svelte";
	import {
		LOCAL_STORAGE_KEY,
		MessageRole,
		MessageType,
		type Message,
	} from "$lib/shared/constant/Interface";
	import {
		getCurrentTimeStamp,
		scrollToBottom,
		scrollToTop,
	} from "$lib/shared/Utils";
	import MessageInput from "$lib/modules/chat/MessageInput.svelte";
	import { fetchTextStream } from "$lib/network/chat/Network"; // 引入后端交互函数
	import LoadingAnimation from "$lib/shared/components/loading/Loading.svelte";
	import "driver.js/dist/driver.css";
	import "$lib/assets/layout/css/driver.css";
	import UploadFile from "$lib/shared/components/upload/uploadFile.svelte";
	import PaperAirplane from "$lib/assets/chat/svelte/PaperAirplane.svelte";
	import Scrollbar from "$lib/shared/components/scrollbar/Scrollbar.svelte";
	import ChatMessage from "$lib/modules/chat/ChatMessage.svelte";
	import { fetchAllFile } from "$lib/network/upload/Network.js";
	import { getNotificationsContext } from "svelte-notifications";
	import { goto } from "$app/navigation";
	let buttonQuery = ""; // 存储按钮属性的变量
	let query: string = "";
	let loading = false; // 控制加载状态
	let scrollToDiv: HTMLDivElement; // 聊天框滚动元素
	let chatMessages: Message[] = data.chatMsg || []; // 使用默认空数组
	const { addNotification } = getNotificationsContext(); // 获取通知上下文
	let isSidebarOpen = false; // 控制侧边栏的打开和关闭
	let isTyping = false; // 控制是否显示打字机效果
	$: knowledge_1 = $knowledge1?.id ? $knowledge1.id : "default";
	const STORAGE_CHAT_KEY_PROJECT = "PROJECT";
	// 页面加载时获取文件
	onMount(() => {
		// 监听图片上传事件
		const handleImageUpload = (event: CustomEvent<{ imageText: string }>) => {
			const { imageText } = event.detail;
			query += imageText; // 将 "@Image" 添加到输入框
		};

		window.addEventListener(
			"imageUploaded",
			handleImageUpload as EventListener
		);

		return () => {
			// 组件销毁时移除事件监听器
			window.removeEventListener(
				"imageUploaded",
				handleImageUpload as EventListener
			);
		};
	});

	// 页面加载时获取文件
	onMount(async () => {
		// sessionStorage.setItem("msg_key", accmulatedMsg);
		scrollToDiv = document
			.querySelector(".chat-scrollbar")
			?.querySelector(".svlr-viewport")!;

		const res = await fetchAllFile();
		if (res) {
			storageFiles.set(res);
		}
		// 读取 localStorage 的聊天记录
		const storedMessages = sessionStorage.getItem(STORAGE_CHAT_KEY_PROJECT);
		if (storedMessages) {
			chatMessages = JSON.parse(storedMessages);
		}

		// 监听 beforeunload 事件，确保聊天记录存储
		const handleBeforeUnload = () => {
			storeMessages();
		};

		window.addEventListener("beforeunload", handleBeforeUnload);

		// 清理事件监听，避免内存泄漏
		onDestroy(() => {
			window.removeEventListener("beforeunload", handleBeforeUnload);
		});
	});

	// 显示通知
	function showNotification(text: string, type: string) {
		addNotification({
			text: text,
			position: "top-left",
			type: type,
			removeAfter: 3000,
		});
	}

	function handleTop() {
		scrollToTop(scrollToDiv);
	}

	function storeMessages() {
		sessionStorage.setItem(
			STORAGE_CHAT_KEY_PROJECT,
			JSON.stringify(chatMessages)
		);
	}

	function decodeEscapedBytes(str: string): string {
		const byteArray = str
			.split("\\x")
			.slice(1)
			.map((byte) => parseInt(byte, 16));
		const decoded = new TextDecoder("utf-8").decode(new Uint8Array(byteArray));

		return decoded;
	}

	function decodeUnicode(str: string): string {
		const decoded = str.replace(/\\u[\dA-Fa-f]{4}/g, (match) => {
			return String.fromCharCode(parseInt(match.replace(/\\u/g, ""), 16));
		});

		return decoded;
	}

	// 处理发送消息
	const handleTextSubmit = async () => {
		loading = true;

		// 清空之前的累积消息
		localStorage.removeItem("msg_key");
		const treeStr = localStorage.getItem("tree");
		console.log(treeStr);
		console.log("query", query);
		// query = `Please generate the mermaid code for a ${buttonQuery} that is required to represent the following: ${query}`;
		query = `项目的目录树如下所示：${treeStr} ${query}`;
		// query = `项目的目录树如下所示：
		// 	\`\`\`
		// 	${treeStr}
		// 	\`\`\`
		// 	${query}`;

		console.log(query);
		const newMessage = {
			role: MessageRole.User,
			type: MessageType.Text,
			content: query,
			time: 0,
		};
		chatMessages = [...chatMessages, newMessage];
		scrollToBottom(scrollToDiv);
		storeMessages();
		query = "";
		console.log("newMessage", newMessage.content);
		await callTextStream(newMessage.content, getCurrentTimeStamp());
		scrollToBottom(scrollToDiv);
		storeMessages();
	};

	// 通过流式接口获取聊天内容
	const callTextStream = async (query: string, startSendTime: number) => {
		try {
			const eventSource = await fetchTextStream(query);
			eventSource.addEventListener("error", (e: any) => {
				if (e.type === "error") {
					showNotification("Failed to load chat content.", "error");
					loading = false;
				}
			});

			eventSource.addEventListener("message", (e: any) => {
				let msg = e.data;
				console.log("msg", msg);

				// Accumulate messages in sessionStorage
				let accumulatedMsg = sessionStorage.getItem("msg_key") || ""; // Get existing messages or start with an empty string
				accumulatedMsg += msg; // Append the new message
				sessionStorage.setItem("msg_key", accumulatedMsg); // Save the accumulated content
				console.log("acc", accumulatedMsg);
				const handleDecodedMessage = (decodedMsg: string) => {
					if (decodedMsg !== "</s>") {
						decodedMsg = decodedMsg.replace(/\\n/g, "\n");
					}

					if (chatMessages[chatMessages.length - 1].role === MessageRole.User) {
						chatMessages.push({
							role: MessageRole.Assistant,
							type: MessageType.Text,
							content: decodedMsg,
							time: startSendTime,
						});
					} else {
						chatMessages[chatMessages.length - 1].content += decodedMsg;
					}

					scrollToBottom(scrollToDiv);
				};

				if (msg.startsWith("b")) {
					let currentMsg = msg.slice(2, -1);

					if (/\\x[\dA-Fa-f]{2}/.test(currentMsg)) {
						currentMsg = decodeEscapedBytes(currentMsg);
					} else if (/\\u[\dA-Fa-f]{4}/.test(currentMsg)) {
						currentMsg = decodeUnicode(currentMsg);
					}

					handleDecodedMessage(currentMsg);
				} else if (msg === "[DONE]") {
					console.log("Done");

					let startTime = chatMessages[chatMessages.length - 1].time;
					loading = false;
					let totalTime = parseFloat(
						((getCurrentTimeStamp() - startTime) / 1000).toFixed(2)
					);

					if (chatMessages.length - 1 !== -1) {
						chatMessages[chatMessages.length - 1].time = totalTime;
					}

					// 清空累积消息
					sessionStorage.removeItem("msg_key");

					storeMessages();
				} else {
					if (/\\x[\dA-Fa-f]{2}/.test(msg)) {
						msg = decodeEscapedBytes(msg);
					} else if (/\\u[\dA-Fa-f]{4}/.test(msg)) {
						msg = decodeUnicode(msg);
					}

					let currentMsg = msg.replace(/"/g, "").replace(/\\n/g, "\n");

					handleDecodedMessage(currentMsg);
				}
			});

			eventSource.stream();
		} catch (error: any) {
			showNotification("Failed to load chat content.", "error");
			loading = false;
		}
	};

	function handleClick(event) {
		const target = event.currentTarget; // 获取当前点击的元素
		buttonQuery = target.getAttribute("data-query") || "";
		console.log("type of chart:", buttonQuery);
	}
	function handelClearHistory() {
		sessionStorage.removeItem(STORAGE_CHAT_KEY_PROJECT);
		chatMessages = [];
	}

	// 处理键盘按下事件，支持 Enter 键发送消息
	const handleKeydown = (event: KeyboardEvent) => {
		if (event.key === "Enter") {
			event.preventDefault(); // 阻止默认行为（例如换行）
			handleTextSubmit(); // 触发发送消息的逻辑
		}
	};

	const directoryTreeRegex = /项目的目录树如下所示："[^"]*"/;
</script>

<!-- 主布局 -->
<div class="flex h-full">
	<!-- 侧边栏 -->
	<div class="fixed left-0 top-0 h-full w-64 bg-[#bfc4da] text-white">
		<div class="p-4">
			<h2 class="mb-6 text-2xl font-bold">Sidebar</h2>
			<ul class="space-y-4">
				<li>
					<button
						on:click={() => goto("/drawer")}
						class="w-full rounded-lg bg-[#654e72] px-4 py-2 text-left text-lg font-semibold transition-all duration-200 ease-in-out hover:bg-[#c7bdd6] focus:bg-gray-600 active:bg-[#c7bdd6]"
					>
						Go to Drawer
					</button>
				</li>
				<li>
					<button
						on:click={() => goto("/project")}
						class="w-full rounded-lg bg-[#654e72] px-4 py-2 text-left text-lg font-semibold transition-all duration-200 ease-in-out hover:bg-[#c7bdd6] focus:bg-gray-600 active:bg-[#c7bdd6]"
					>
						Go to Project
					</button>
				</li>
			</ul>
		</div>
	</div>

	<!-- 主内容 -->
	<div class="main-content ml-64 flex flex-1 flex-col p-4">
		<!-- 聊天显示区域 -->
		<div
			class="flex-1 overflow-auto rounded-lg border border-[#b1a9da] bg-white p-4"
			style="display: flex; flex-direction: column;"
		>
			<div class="flex flex-col gap-4">
				<div class="flex justify-between p-0">
					<p class="text-[1.7rem] font-bold tracking-tight text-[#6c80a9]">
						Project
					</p>
				</div>

				<!-- 聊天消息 -->
				<div
					class="flex flex-col gap-2 overflow-auto"
					style="overflow: auto; font-size: 1.1em;"
				>
					{#each chatMessages as message, i}
						<ChatMessage
							on:scrollTop={() => handleTop()}
							msg={{
								...message,
								content: message.content.replace(
									directoryTreeRegex,
									"@Project "
								),
							}}
							style="font-size: 1.5em;"
							class="text-2xl"
						/>
					{/each}
					<p>{chatMessages.length} messages in total</p>
					{#if loading}
						<div
							style="height: 50px; display: flex; align-items: center; justify-content: center;"
						>
							<div class="spinner" />
						</div>
					{/if}
				</div>

				<!-- 加载动画 -->
			</div>
		</div>

		<!-- 聊天输入区域 -->
		<div class="chat-container flex w-full items-center gap-2">
			<!-- 输入框 -->
			<div class="relative flex-grow">
				<input
					type="text"
					class="chat-input"
					bind:value={query}
					placeholder="Type your message..."
					on:keydown={handleKeydown}
				/>
			</div>

			<!-- 上传按钮 -->
			<div class="upload-btn-wrapper">
				<UploadFile />
			</div>

			<!-- 发送按钮 -->
			<button class="send-button" on:click={() => query && handleTextSubmit()}>
				<span><PaperAirplane /></span>
			</button>
		</div>
	</div>
</div>

<style>
	.spinner {
		border: 4px solid #f3f3f3;
		border-top: 4px solid #705e78;
		border-radius: 50%;
		width: 20px;
		height: 20px;
		animation: spin 1s linear infinite;
	}

	@keyframes spin {
		0% {
			transform: rotate(0deg);
		}
		100% {
			transform: rotate(360deg);
		}
	}
	button {
		background-color: #654e72;
		color: white;
		padding: 10px 20px;
		border: none;
		border-radius: 5px;
		cursor: pointer;
	}

	button:hover {
		background-color: #c7bdd6;
	}
	.chat-container {
		display: flex;
		align-items: center; /* 让所有元素垂直居中 */
		width: 100%;
		padding: 10px;
		gap: 0px; /* 增加间距 */
	}

	.chat-messages {
		padding-bottom: 80px; /* 为输入框留出空间 */
	}

	.chat-input {
		width: calc(100%);
		font-size: 1rem;
		padding: 12px 16px;
		height: 40px;
		border-radius: 25px;
		border: 1px solid #b1a9da;
		background-color: #fff;
	}

	.upload-btn-wrapper {
		display: flex;
		align-items: center;
	}

	button.send-button {
		width: 40px;
		height: 40px;
		background-color: #876899;
		border: none;
		border-radius: 50%;
		display: flex;
		align-items: center;
		justify-content: center;
		cursor: pointer;
		transition: background-color 0.2s ease-in-out;
		box-shadow: 0 2px 4px rgb(255, 255, 255);
	}
	button.send-button span {
		display: flex;
	}
	.send-button:hover {
		background-color: #705e78;
	}

	.upload-btn {
		width: 40px;
		height: 40px;
		border-radius: 50%;
		background-color: white;
		color: white;
		font-size: 1.2rem;
		cursor: pointer;
		transition: all 0.3s ease-in-out;
	}

	.upload-btn:hover {
		width: 150px;
		background-color: white;
		border-radius: 25px;
	}

	.upload-tooltip {
		position: absolute;
		left: 50px;
		top: 50%;
		transform: translateY(-50%);
		background-color: rgba(0, 0, 0, 0.75);
		color: white;
		padding: 5px 10px;
		border-radius: 4px;
		font-size: 0.9rem;
		visibility: hidden;
		opacity: 0;
		transition: opacity 0.3s ease, transform 0.3s ease;
	}

	.upload-btn:hover .upload-tooltip {
		visibility: visible;
		opacity: 1;
		transform: translateX(10px);
	}

	/* 输入框和发送按钮 */

	.chat-input:focus {
		border-color: #a58db3;
		box-shadow: 0 0 8px rgba(0, 123, 255, 0.2);
	}

	.flex-1 {
		padding-left: 20px; /* 增加左侧内边距，让聊天框的边框和内容区更远离侧边栏 */
	}
</style>